/**
 * 移库系统API服务类
 * 基于明道云低代码平台，参考拣货系统架构
 */

import { api } from 'mdye'

// ✅ 添加调试日志：检查API对象
console.log('🔧 MDYE API对象检查:', {
  api对象存在: !!api,
  api类型: typeof api,
  api内容: api,
  worksheet存在: !!(api && api.worksheet),
  getFilterRows存在: !!(api && api.worksheet && api.worksheet.getFilterRows)
});

// ✅ 如果API不存在，尝试从window获取
let worksheetApi = api?.worksheet;
if (!worksheetApi && typeof window !== 'undefined') {
  console.log('🔧 从window对象获取API...');
  worksheetApi = window.api?.worksheet;
  console.log('window.api.worksheet存在:', !!worksheetApi);
}

// ================= 动态配置工具（运行时从 window.mdye.env.config 读取） =================
function getEnvRoot() {
  try {
    if (typeof window !== 'undefined') {
      // 优先当前窗口
      if (window.mdye && window.mdye.env && window.mdye.env.config) return window.mdye.env.config
      if (window.env && window.env.config) return window.env.config
      if (window.mdye && window.mdye.config) return window.mdye.config
      if (window.config) return window.config
      // 再尝试父窗口
      if (window.parent && window.parent !== window) {
        try {
          if (window.parent.mdye && window.parent.mdye.env && window.parent.mdye.env.config) {
            return window.parent.mdye.env.config
          }
          if (window.parent.env && window.parent.env.config) {
            return window.parent.env.config
          }
          if (window.parent.mdye && window.parent.mdye.config) {
            return window.parent.mdye.config
          }
          if (window.parent.config) {
            return window.parent.config
          }
        } catch (e) {}
      }
      // 顶层窗口兜底
      if (window.top && window.top !== window) {
        try {
          if (window.top.mdye && window.top.mdye.env && window.top.mdye.env.config) {
            return window.top.mdye.env.config
          }
          if (window.top.env && window.top.env.config) {
            return window.top.env.config
          }
          if (window.top.mdye && window.top.mdye.config) {
            return window.top.mdye.config
          }
          if (window.top.config) {
            return window.top.config
          }
        } catch (e) {}
      }
    }
  } catch (e) {
    // 跨域场景下访问 parent/top 可能报错，忽略
  }
  return {}
}

function getEnvValue(key) {
  const candidates = []
  const pushCfg = (obj) => { if (obj && typeof obj === 'object') candidates.push(obj) }
  
  // 收集多个可能的配置根
  try {
    if (typeof window !== 'undefined') {
      pushCfg(window.mdye?.env?.config)
      pushCfg(window.env?.config)
      pushCfg(window.mdye?.config)
      pushCfg(window.config)
      if (window.parent && window.parent !== window) {
        try {
          pushCfg(window.parent.mdye?.env?.config)
          pushCfg(window.parent.env?.config)
          pushCfg(window.parent.mdye?.config)
          pushCfg(window.parent.config)
        } catch (e) {}
      }
      if (window.top && window.top !== window) {
        try {
          pushCfg(window.top.mdye?.env?.config)
          pushCfg(window.top.env?.config)
          pushCfg(window.top.mdye?.config)
          pushCfg(window.top.config)
        } catch (e) {}
      }
    }
  } catch (e) {}

  // 1) 直接匹配 - 支持对象格式
  for (const cfg of candidates) {
    if (cfg && !Array.isArray(cfg) && Object.prototype.hasOwnProperty.call(cfg, key)) {
      return cfg[key]
    }
  }
  
  // 1.5) 明道云插件数组格式直接匹配
  for (const cfg of candidates) {
    if (Array.isArray(cfg)) {
      for (const item of cfg) {
        if (item && item.fieldId === key) {
          const value = item.value || item.default || '';
          console.log(`🎯 明道云插件配置匹配: ${key} = "${value}" (来源: fieldId)`);
          return value;
        }
      }
    }
  }
  
  // 2) 不区分大小写匹配
  const lower = key.toLowerCase()
  for (const cfg of candidates) {
    if (!cfg) continue
    if (!Array.isArray(cfg)) {
      for (const k of Object.keys(cfg)) {
        if (k.toLowerCase() === lower) return cfg[k]
      }
    }
  }
  
  // 2.5) 明道云插件格式 - 不区分大小写匹配fieldId
  for (const cfg of candidates) {
    if (Array.isArray(cfg)) {
      for (const item of cfg) {
        if (item && item.fieldId && item.fieldId.toLowerCase() === lower) {
          const value = item.value || item.default || '';
          console.log(`🎯 明道云插件配置匹配(忽略大小写): ${key} = "${value}"`);
          return value;
        }
      }
    }
  }
  
  // 3) 常见别名映射
  const aliasMap = {
    'AppKey': ['appKey','APPKEY','app_key'],
    'Sign': ['sign','SIGN','appSign','app_sign','明道云签名'],
    'SecretKey': ['secretKey','SECRETKEY','secret_key','明道云密钥'],
    'LOCATION_STOCK': ['location_stock','LOCATIONSTOCK','库位库存表ID'],
    'TRANSFER_ORDERS': ['transfer_orders','TRANSFERORDERS','移库单工作表'],
    'LOCATION_MANAGEMENT': ['location_management','LOCATIONMANAGEMENT','库位管理工作表'],
    'webhookUrl': ['webhookURL','WEBHOOKURL','webhook_url','移库系统Webhook']
  }
  
  const aliases = aliasMap[key] || []
  
  // 3.1) 对象格式别名匹配
  for (const cfg of candidates) {
    if (!cfg || Array.isArray(cfg)) continue
    for (const a of aliases) {
      if (Object.prototype.hasOwnProperty.call(cfg, a)) {
        console.log(`🎯 对象别名匹配: ${key} = "${cfg[a]}" (通过别名: ${a})`);
        return cfg[a];
      }
    }
  }
  
  // 3.2) 明道云插件格式别名匹配 - 通过controlName
  for (const cfg of candidates) {
    if (Array.isArray(cfg)) {
      for (const item of cfg) {
        if (item && item.controlName) {
          for (const a of aliases) {
            if (item.controlName === a) {
              const value = item.value || item.default || '';
              console.log(`🎯 明道云插件controlName匹配: ${key} = "${value}" (通过别名: ${a})`);
              return value;
            }
          }
        }
      }
    }
  }
  
  console.warn(`⚠️ 配置项 "${key}" 未找到，已尝试的别名:`, aliases);
  return ''
}

function getEnvAny(keys) {
  const cfg = getEnvRoot()
  if (!cfg || typeof cfg !== 'object') return ''
  for (const k of keys) {
    if (cfg[k]) return cfg[k]
  }
  return ''
}

function requireEnv(key, displayName = key) {
  const value = getEnvValue(key)
  if (!value) {
    throw new Error(`缺少运行时配置: ${displayName} (${key})`)
  }
  return value
}

class TransferApiService {
  constructor() {
    if (TransferApiService.instance) {
      return TransferApiService.instance
    }
    
    // 延迟初始化（避免模块加载时 mdye 环境尚未注入）
    this._initialized = false
    this.API_CONFIG = {
      baseURL: 'https://www.dachen.vip/api/v2/open/worksheet',
      appKey: '',
      sign: '',
      secretKey: ''
    }
    this.appKey = ''
    this.secretKey = ''
    this.sign = ''
    
    // 本地存储的移库单详细数据
    this.localTransferOrders = this.loadLocalTransferOrders()
    
    // 工作表ID占位，实际在 init() 中读取
    this.WORKSHEET_IDS = {
      LOCATION_STOCK: '',
      TRANSFER_ORDERS: '',
      LOCATION_MANAGEMENT: ''
    }
    
    // 字段ID配置
    this.FIELD_IDS = {
      // 移库单字段（正确的明道云字段ID）
      TRANSFER_TYPE: '6864d7ae4e2949f411990f05',       // 移库类型
      TRANSFER_NUMBER: '6864d7ae4e2949f411990eff',     // 移库单号  
      TRANSFER_STATUS: '6864d7ae4e2949f411990f00',     // 移库状态
      TRANSFER_CREATE_TIME: '6864d7ae4e2949f411990f01', // 创建时间
      TRANSFER_FROM_LOCATION: '68a6c2f6096ba6d65c501566', // 移出库位 ✅ 正确字段ID
      TRANSFER_TO_LOCATION: '68a6c2f6096ba6d65c501565',   // 移入库位 ✅ 正确字段ID
      TRANSFER_QUANTITY: '68a6c55a096ba6d65c501671',      // 移库数量 ✅ 新增字段ID
      // 注意：还需要商品名称字段ID，如果有的话请提供
      
      // 库位库存字段（来自拣货系统）
      PRODUCT_NAME: '688321482430e5add306b0c6',        // 商品名称
      PRODUCT_BARCODE: '688321df2430e5add306b0e7',     // 商品条码
      SUPPLIER_NAME: '688320a62430e5add306b0a0',       // 供应商名称
      PRODUCTION_DATE: '6879ee6d8371cd243659b10a',     // 生产日期
      LOCATION_CODE: '687b366a9655bb248e31d44d',       // 库位编码
      AVAILABLE_STOCK: '6891613df6303e511c9a76ba',     // 可用库存 ✅ 新增正确字段
      LOCKED_STOCK: '689dad82c82bfc2f84b3ba38',        // 锁定库存
      STOCK_QUANTITY: '689edaf7a92ea0c35cc9c8d7',     // 库存数量
      
      // 库位管理字段
      LOCATION_MANAGEMENT_CODE: '686650f557603df8e65d26a9'  // 库位管理表中的库位编码字段
    }
    
    // 排除的库位编码（仅对普通移库和良品转残生效）
    this.EXCLUDED_LOCATIONS = [
      'JH-01-01-01-01',  // 进货库位
      'CP-01-01-01-01',  // 残品库位
      'SH-01-01-01-01',  // 损耗库位
      'CY-01-01-01-01'   // 其他特殊库位
      // 注意：A4-01-01-01-01 不在排除列表中，应该是正常库位
    ]
    
    // 残品库位编码
    this.DEFECTIVE_LOCATION = 'CP-01-01-01-01'

    // Webhook 动态地址（延迟读取）
    this.webhookUrl = ''
    
    TransferApiService.instance = this
  }

  init() {
    if (this._initialized) return
    // 读取运行时配置
    const cfgCandidates = {
      'window.mdye.env.config': (typeof window !== 'undefined') ? window.mdye?.env?.config : undefined,
      'window.env.config': (typeof window !== 'undefined') ? window.env?.config : undefined,
      'window.mdye.config': (typeof window !== 'undefined') ? window.mdye?.config : undefined,
      'window.config': (typeof window !== 'undefined') ? window.config : undefined
    }
    try { if (typeof window !== 'undefined' && window.parent && window.parent !== window) {
      cfgCandidates['parent.mdye.env.config'] = window.parent.mdye?.env?.config
      cfgCandidates['parent.env.config'] = window.parent.env?.config
      cfgCandidates['parent.mdye.config'] = window.parent.mdye?.config
      cfgCandidates['parent.config'] = window.parent.config
    }} catch(e) {}
    try { if (typeof window !== 'undefined' && window.top && window.top !== window) {
      cfgCandidates['top.mdye.env.config'] = window.top.mdye?.env?.config
      cfgCandidates['top.env.config'] = window.top.env?.config
      cfgCandidates['top.mdye.config'] = window.top.mdye?.config
      cfgCandidates['top.config'] = window.top.config
    }} catch(e) {}
    console.log('🔧 环境配置候选来源（仅用于调试）:', Object.fromEntries(Object.entries(cfgCandidates).map(([k,v])=>[k, !!v])))
    Object.entries(cfgCandidates).forEach(([k,v]) => {
      if (v && typeof v === 'object') {
        console.log(`🔧 ${k} 可用键:`, Object.keys(v))
      }
    })

    this.API_CONFIG = {
      baseURL: 'https://www.dachen.vip/api/v2/open/worksheet',
      appKey: getEnvValue('AppKey'),
      sign: getEnvValue('Sign'),
      secretKey: getEnvValue('SecretKey')
    }
    this.appKey = this.API_CONFIG.appKey
    this.secretKey = this.API_CONFIG.secretKey
    this.sign = this.API_CONFIG.sign

    this.WORKSHEET_IDS = {
      LOCATION_STOCK: getEnvValue('LOCATION_STOCK'),
      TRANSFER_ORDERS: getEnvValue('TRANSFER_ORDERS'),
      LOCATION_MANAGEMENT: getEnvValue('LOCATION_MANAGEMENT')
    }

    this.webhookUrl = getEnvValue('webhookUrl') || ''
    // 关键配置缺失时仅警告，不抛出异常，防止页面初始化中断
    const missing = []
    if (!this.API_CONFIG.appKey) missing.push('AppKey')
    if (!this.API_CONFIG.sign) missing.push('Sign')
    if (!this.WORKSHEET_IDS.LOCATION_STOCK) missing.push('LOCATION_STOCK')
    if (!this.WORKSHEET_IDS.TRANSFER_ORDERS) missing.push('TRANSFER_ORDERS')
    if (!this.WORKSHEET_IDS.LOCATION_MANAGEMENT) missing.push('LOCATION_MANAGEMENT')
    if (missing.length) {
      console.warn('⚠️ 缺少运行时配置（不阻断初始化）:', missing)
    }
    this._initialized = true
  }

  ensureInitialized() {
    if (!this._initialized) this.init()
  }

  /**
   * 安全的API调用封装 - 使用明道云标准调用方式
   */
  async callApi(method, params) {
    console.log(`📡 调用API: ${method}`, params);
    
    try {
      // 直接使用明道云标准API调用
      if (typeof window !== 'undefined' && window.api && window.api.call) {
        console.log(`📡 使用 window.api.call('worksheet', '${method}')`);
        const result = await window.api.call('worksheet', method, params);
        console.log(`📥 API响应成功:`, result);
        return result;
      } else {
        throw new Error(`window.api.call 不可用，请检查明道云环境`);
      }
    } catch (error) {
      console.error(`❌ API调用失败 ${method}:`, error);
      throw error;
    }
  }

  /**
   * 验证库位编码是否存在于库位管理表中
   * @param {string} locationCode - 库位编码
   * @returns {Promise<boolean>} 库位是否存在
   */
  async validateLocationExists(locationCode) {
    this.ensureInitialized()
    try {
      console.log(`🔍 验证库位编码是否存在: "${locationCode}"`)
      
      if (!locationCode || !locationCode.trim()) {
        console.warn('⚠️ 库位编码为空')
        return false
      }
      
      // ✅ 精准的字符串处理 - 移除前后空格但保持原始大小写
      const trimmedCode = locationCode.trim()
      
      console.log(`🔍 精准匹配模式 - 输入处理:`, {
        原始输入: `"${locationCode}"`,
        处理后: `"${trimmedCode}"`,
        长度: trimmedCode.length,
        字符编码: Array.from(trimmedCode).map(c => c.charCodeAt(0))
      })
      
      // 详细的API调用参数日志 - 使用精准匹配
      const requestParams = {
        worksheetId: this.WORKSHEET_IDS.LOCATION_MANAGEMENT,
        filters: [
          {
            controlId: this.FIELD_IDS.LOCATION_MANAGEMENT_CODE,
            value: trimmedCode,
            dataType: 2,        // 文本类型
            spliceType: 1       // 1=精确匹配 (不是包含匹配)
          }
        ],
        pageSize: 10
      }
      
      console.log(`📤 API请求参数:`, JSON.stringify(requestParams, null, 2))
      
      // 查询库位管理表
      const response = await this.callApi('getFilterRows', requestParams)
      
      console.log(`📥 API响应数据:`, {
        success: !!response,
        hasData: !!(response && response.data),
        dataType: typeof response?.data,
        dataLength: response?.data?.length || 0,
        fullResponse: response
      })
      
      // 如果有数据，显示前几条记录用于调试并进行精准匹配验证
      let exactMatches = []
      if (response && response.data && response.data.length > 0) {
        console.log(`📋 API返回的库位记录 (${response.data.length}条):`)
        
        response.data.forEach((record, index) => {
          const recordLocationCode = record[this.FIELD_IDS.LOCATION_MANAGEMENT_CODE]
          console.log(`  记录 ${index + 1}:`, {
            rowid: record.rowid,
            locationCode: recordLocationCode,
            inputCode: trimmedCode,
            exactMatch: recordLocationCode === trimmedCode
          })
          
          // ✅ 客户端精准匹配验证 - 字符级别完全匹配
          if (recordLocationCode) {
            const recordTrimmed = recordLocationCode.trim()
            const isExactMatch = recordTrimmed === trimmedCode
            
            console.log(`    匹配检查:`, {
              数据库值: `"${recordTrimmed}"`,
              输入值: `"${trimmedCode}"`,
              长度匹配: recordTrimmed.length === trimmedCode.length,
              字符匹配: isExactMatch,
              大小写敏感: true
            })
            
            if (isExactMatch) {
              exactMatches.push(record)
            }
          }
        })
        
        console.log(`🎯 精准匹配结果: 找到 ${exactMatches.length} 个完全匹配的记录`)
      }
      
      console.log(`📊 库位管理表查询结果:`, {
        查询库位: trimmedCode,
        API返回数据: response?.data?.length || 0,
        精准匹配数量: exactMatches.length,
        工作表ID: this.WORKSHEET_IDS.LOCATION_MANAGEMENT,
        字段ID: this.FIELD_IDS.LOCATION_MANAGEMENT_CODE
      })
      
      // ✅ 使用精准匹配结果而非API原始结果
      const exists = exactMatches.length > 0
      
      if (exists) {
        console.log(`✅ 库位编码 "${trimmedCode}" 存在于库位管理表中`)
      } else {
        console.warn(`❌ 库位编码 "${trimmedCode}" 不存在于库位管理表中`)
      }
      
      return exists
      
    } catch (error) {
      console.error('❌ 验证库位编码时发生错误:', error)
      console.error('错误详情:', {
        message: error.message,
        stack: error.stack,
        requestedLocation: locationCode
      })
      // 抛出错误，让调用方决定如何处理
      throw new Error(`库位验证失败: ${error.message}`)
    }
  }

  /**
   * 测试库位管理表连接和数据获取
   * @returns {Promise<Object>} 测试结果
   */
  async testLocationManagementConnection() {
    this.ensureInitialized()
    try {
      console.log('🔍 测试库位管理表连接...')
      console.log('📋 使用的配置信息:')
      console.log(`  库位管理表ID: ${this.WORKSHEET_IDS.LOCATION_MANAGEMENT}`)
      console.log(`  库位编码字段ID: ${this.FIELD_IDS.LOCATION_MANAGEMENT_CODE}`)
      
      // 先测试基本连接 - 获取库位管理表的前几条记录
      console.log('📤 发送API请求...')
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_MANAGEMENT,
        pageSize: 5
      })
      
      console.log('📥 收到API响应:')
      console.log('  响应存在:', !!response)
      console.log('  响应类型:', typeof response)
      console.log('  完整响应:', response)
      
      if (response) {
        console.log('  data字段存在:', 'data' in response)
        console.log('  data类型:', typeof response.data)
        console.log('  data长度:', response.data?.length)
      }
      
      console.log('📊 库位管理表连接测试结果:', {
        成功: !!response,
        有数据: !!(response && response.data),
        记录数: response?.data?.length || 0,
        工作表ID: this.WORKSHEET_IDS.LOCATION_MANAGEMENT,
        字段ID: this.FIELD_IDS.LOCATION_MANAGEMENT_CODE
      })
      
      if (response && response.data && response.data.length > 0) {
        console.log('📋 库位管理表示例数据:')
        response.data.forEach((record, index) => {
          console.log(`  记录 ${index + 1}:`)
          console.log(`    rowid: ${record.rowid}`)
          console.log(`    指定字段值: ${record[this.FIELD_IDS.LOCATION_MANAGEMENT_CODE]}`)
          console.log(`    所有字段键:`, Object.keys(record))
          console.log(`    原始记录:`, record)
          
          // 尝试查找可能的库位编码字段
          const possibleLocationFields = Object.keys(record).filter(key => 
            key.toLowerCase().includes('location') || 
            key.toLowerCase().includes('位置') ||
            key.toLowerCase().includes('库位') ||
            key.includes('686650f557603df8e65d26a9')
          )
          console.log(`    可能的库位字段:`, possibleLocationFields)
        })
      } else {
        console.warn('⚠️ 没有获取到任何数据，可能的原因:')
        console.warn('  1. 工作表ID不正确')
        console.warn('  2. 工作表为空')
        console.warn('  3. 权限不足')
        console.warn('  4. 网络问题')
      }
      
      return {
        success: !!response,
        recordCount: response?.data?.length || 0,
        hasData: !!(response && response.data && response.data.length > 0),
        rawResponse: response
      }
      
    } catch (error) {
      console.error('❌ 库位管理表连接测试失败:', error)
      console.error('错误详情:', {
        message: error.message,
        stack: error.stack,
        name: error.name
      })
      return {
        success: false,
        error: error.message,
        errorDetails: error
      }
    }
  }

  /**
   * 自动检测库位管理表的正确字段ID
   * @returns {Promise<string|null>} 检测到的字段ID
   */
  async detectLocationFieldId() {
    try {
      console.log('🔍 自动检测库位编码字段ID...')
      
      // 获取库位管理表的前几条记录
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_MANAGEMENT,
        pageSize: 3
      })
      
      if (!response || !response.data || response.data.length === 0) {
        console.warn('⚠️ 无法获取库位管理表数据进行字段检测')
        return null
      }
      
      console.log('📋 分析字段结构...')
      const firstRecord = response.data[0]
      const allFields = Object.keys(firstRecord)
      
      // 分析每个字段的值，寻找可能的库位编码
      const candidates = []
      
      allFields.forEach(fieldId => {
        const value = firstRecord[fieldId]
        if (typeof value === 'string' && value.trim()) {
          // 检查是否像库位编码格式
          const isLocationLike = /^[A-Z]{1,3}-?\d{2}-?\d{2}-?\d{2}(-?\d{2})?$/i.test(value.trim()) ||
                                /^[A-Z]{2,4}\d{6,8}$/i.test(value.trim())
          
          if (isLocationLike) {
            candidates.push({
              fieldId,
              value: value.trim(),
              confidence: 'high'
            })
          }
        }
      })
      
      console.log('🎯 库位编码字段候选:')
      candidates.forEach(candidate => {
        console.log(`  字段ID: ${candidate.fieldId}`)
        console.log(`  示例值: ${candidate.value}`)
        console.log(`  置信度: ${candidate.confidence}`)
      })
      
      // 如果找到候选字段，返回第一个
      if (candidates.length > 0) {
        const detectedFieldId = candidates[0].fieldId
        console.log(`✅ 检测到可能的库位编码字段ID: ${detectedFieldId}`)
        return detectedFieldId
      } else {
        console.warn('❌ 未检测到明显的库位编码字段')
        return null
      }
      
    } catch (error) {
      console.error('❌ 字段ID检测失败:', error)
      return null
    }
  }

  /**
   * 获取所有可用商品列表
   * @returns {Promise<Array>} 商品名称数组
   */
  async getAvailableProducts() {
    this.ensureInitialized()
    try {
      console.log('开始获取可用商品列表...')
      
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_STOCK,
        pageSize: 200
      })
      
      if (response && response.data) {
        const products = new Set()
        response.data.forEach(row => {
          const productName = row[this.FIELD_IDS.PRODUCT_NAME]
          if (productName && productName.trim()) {
            products.add(productName.trim())
          }
        })
        
        const productList = Array.from(products).sort()
        console.log(`获取到 ${productList.length} 个商品:`, productList)
        return productList
      }
      
      console.warn('未获取到商品数据')
      return []
      
    } catch (error) {
      console.error('获取商品列表失败:', error)
      throw error
    }
  }

  /**
   * 根据商品名称和移库类型获取可用库位
   * @param {string} productName - 商品名称
   * @param {string} transferType - 移库类型 (normal/good-to-bad/bad-to-good)
   * @returns {Promise<Array>} 库位信息数组
   */
  async getAvailableLocations(productName, transferType) {
    this.ensureInitialized()
    try {
      console.log(`获取库位列表 - 商品: ${productName}, 类型: ${transferType}`)
      
      if (!productName) {
        return []
      }

      const filters = [
        {
          controlId: this.FIELD_IDS.PRODUCT_NAME,
          value: productName,
          dataType: 2,
          spliceType: 1
        }
      ]

      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_STOCK,
        filters: filters,
        pageSize: 200
      })
      
      if (response && response.data) {
        let locations = response.data.map(row => ({
          id: row.rowid,
          locationCode: row[this.FIELD_IDS.LOCATION_CODE] || '',
          productName: row[this.FIELD_IDS.PRODUCT_NAME] || '',
          supplierName: row[this.FIELD_IDS.SUPPLIER_NAME] || '',
          productionDate: row[this.FIELD_IDS.PRODUCTION_DATE] || '',
          lockedStock: parseInt(row[this.FIELD_IDS.LOCKED_STOCK] || '0'),
          stockQuantity: parseInt(row[this.FIELD_IDS.STOCK_QUANTITY] || '0'),
          rawData: row
        }))

        // 根据移库类型过滤库位
        locations = locations.filter(location => {
          // 只显示有库存的库位
          if (location.lockedStock <= 0) {
            return false
          }

          if (transferType === 'bad-to-good') {
            // 残品转良：只能从CP-01-01-01-01移出
            return location.locationCode === this.DEFECTIVE_LOCATION
          } else {
            // 普通移库和良品转残：排除特殊库位
            return !this.EXCLUDED_LOCATIONS.includes(location.locationCode)
          }
        })

        console.log(`过滤后的库位数量: ${locations.length}`)
        return locations
      }
      
      return []
      
    } catch (error) {
      console.error('获取库位列表失败:', error)
      throw error
    }
  }

  /**
   * 创建移库单
   * @param {Object} transferData - 移库单数据
   * @returns {Promise<Object>} 创建结果
   */
  async createTransferOrder(transferData) {
    this.ensureInitialized()
    try {
      console.log('创建移库单:', transferData)
      
      const {
        transferType,
        transferNumber,
        productName,
        productBarcode,
        fromLocationCode,
        toLocationCode,
        quantity,
        fromLocationId,
        supplierName,
        productionDate
      } = transferData

      // ✅ 构建移库单控件数据 - 使用正确的字段ID
      const controls = [
        {
          controlId: this.FIELD_IDS.TRANSFER_TYPE,
          value: this.getTransferTypeName(transferType) // 保存中文名称便于明道云显示
        },
        {
          controlId: this.FIELD_IDS.TRANSFER_NUMBER,
          value: transferNumber
        },
        {
          controlId: this.FIELD_IDS.TRANSFER_STATUS,
          value: 'completed' // ✅ 修改为已完成状态
        },
        {
          controlId: this.FIELD_IDS.TRANSFER_FROM_LOCATION,
          value: fromLocationCode || ''
        },
        {
          controlId: this.FIELD_IDS.TRANSFER_TO_LOCATION,
          value: toLocationCode || ''
        },
        {
          controlId: this.FIELD_IDS.TRANSFER_QUANTITY,
          value: parseInt(quantity) || 0 // ✅ 添加移库数量
        },
        {
          controlId: this.FIELD_IDS.TRANSFER_CREATE_TIME,
          value: new Date().toISOString() // ✅ 使用当前触发时间作为创建时间
        }
      ]
      
      console.log('📝 构建移库单控件数据:', {
        移库类型: this.getTransferTypeName(transferType),
        移库单号: transferNumber,
        移库状态: 'completed', // ✅ 显示已完成状态
        移出库位: fromLocationCode,
        移入库位: toLocationCode,
        移库数量: parseInt(quantity),
        创建时间: new Date().toLocaleString('zh-CN'), // ✅ 显示触发时间
        controls: controls
      })
      
      const requestData = {
        worksheetId: this.WORKSHEET_IDS.TRANSFER_ORDERS,
        controls: controls
      }
      
      // ✅ 使用直接的HTTP请求创建移库单记录
      const result = await this.addRowToWorksheet(requestData)
      console.log('移库单创建成功:', result)
      
      // 存储完整的移库数据到本地存储中，用于列表显示
      const fullTransferData = {
        id: result.data?.rowid || result.rowid || Date.now().toString(),
        transferType,
        transferNumber,
        productName,
        fromLocationCode,
        toLocationCode,
        quantity: parseInt(quantity),
        status: 'completed', // ✅ 修改为已完成状态
        createTime: new Date().toISOString(), // ✅ 使用触发时间
        typeName: this.getTransferTypeName(transferType)
      }
      
      // 保存到本地存储
      this.saveTransferOrderToLocal(fullTransferData)
      
      // ✅ 发送webhook到明道云
      try {
        console.log('📤 开始发送移库单信息到明道云工作流...')
        
        // 根据移库类型确定正确的移出和移入库位
        let actualFromLocation = fromLocationCode
        let actualToLocation = toLocationCode
        
        if (transferType === 'good-to-bad') {
          // 良品转残：移入固定为残品库位
          actualToLocation = this.DEFECTIVE_LOCATION
        } else if (transferType === 'bad-to-good') {
          // 残品转良：移出固定为残品库位
          actualFromLocation = this.DEFECTIVE_LOCATION
        }

        const webhookData = {
          移库类型: this.getTransferTypeName(transferType),
          商品名称: productName,
          商品条码: productBarcode || '',
          生产日期: productionDate || '',
          移出库位: actualFromLocation,
          移入库位: actualToLocation,
          移库数量: quantity,
          移库单号: transferNumber,
          供应商: supplierName || '',
          移库状态: 'completed', // ✅ 添加移库状态到webhook
          创建时间: new Date().toLocaleString('zh-CN', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
          }) // ✅ 使用触发时间的中文格式
        }
        
        await this.sendWebhook(webhookData)
        console.log('✅ 移库单信息已成功发送到明道云工作流')
      } catch (webhookError) {
        console.error('⚠️ 发送到明道云工作流失败:', webhookError)
        // Webhook失败不影响移库单创建，继续执行
      }
      
      return {
        success: true,
        data: result,
        transferId: result.data?.rowid || result.rowid || result.data?.row_id
      }
      
    } catch (error) {
      console.error('创建移库单失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 添加行记录到工作表
   * @param {Object} requestData - 请求数据
   * @returns {Promise<Object>} 创建结果
   */
  async addRowToWorksheet(requestData) {
    this.ensureInitialized()
    try {
      console.log('📝 创建工作表记录:', requestData)
      
      // 使用明道云内置API
      const result = await this.callApi('addWorksheetRow', {
        worksheetId: requestData.worksheetId,
        controls: requestData.controls
      })
      
      console.log('📝 工作表记录创建成功:', result)
      return result
      
    } catch (error) {
      console.error('创建工作表记录错误:', error)
      throw error
    }
  }

  /**
   * 发送webhook到明道云
   * @param {Object} data - 要发送的数据
   * @returns {Promise<Object>} 发送结果
   */
  async sendWebhook(data) {
    this.ensureInitialized()
    try {
      console.log('📤 发送Webhook数据:', data)
      
      const webhookUrl = this.webhookUrl
      if (!webhookUrl) throw new Error('未配置 webhookUrl')
      
      const response = await fetch(webhookUrl, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        },
        body: JSON.stringify(data)
      })
      
      if (!response.ok) {
        throw new Error(`Webhook请求失败: ${response.status} ${response.statusText}`)
      }
      
      const responseData = await response.json()
      console.log('📥 Webhook响应:', responseData)
      
      return {
        success: true,
        data: responseData
      }
      
    } catch (error) {
      console.error('Webhook发送错误:', error)
      throw error
    }
  }

  /**
   * 获取移库单列表 - 混合使用明道云数据和本地存储
   * @param {Object} options - 查询选项
   * @returns {Promise<Array>} 移库单列表
   */
  async getTransferOrders(options = {}) {
    this.ensureInitialized()
    try {
      console.log('获取移库单列表（使用明道云数据）...')
      
      const { status, transferType, pageSize = 50 } = options
      
      const filters = []
      
      if (status) {
        filters.push({
          controlId: this.FIELD_IDS.TRANSFER_STATUS,
          value: status,
          dataType: 2,
          spliceType: 1
        })
      }
      
      if (transferType) {
        filters.push({
          controlId: this.FIELD_IDS.TRANSFER_TYPE,
          value: this.getTransferTypeName(transferType), // 使用中文名称查询
          dataType: 2,
          spliceType: 1
        })
      }

      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.TRANSFER_ORDERS,
        filters: filters.length > 0 ? filters : undefined,
        pageSize: pageSize
      })
      
      if (response && response.data) {
        const transferOrders = response.data.map(row => ({
          id: row.rowid,
          transferType: row[this.FIELD_IDS.TRANSFER_TYPE] || '', // 这里是中文名称
          transferNumber: row[this.FIELD_IDS.TRANSFER_NUMBER] || '',
          status: row[this.FIELD_IDS.TRANSFER_STATUS] || 'completed', // ✅ 默认为已完成状态
          fromLocationCode: row[this.FIELD_IDS.TRANSFER_FROM_LOCATION] || '',
          toLocationCode: row[this.FIELD_IDS.TRANSFER_TO_LOCATION] || '',
          quantity: parseInt(row[this.FIELD_IDS.TRANSFER_QUANTITY] || '0'), // ✅ 添加移库数量字段
          createTime: row[this.FIELD_IDS.TRANSFER_CREATE_TIME] || row.ctime || '', // ✅ 优先使用自定义创建时间字段
          updateTime: row.utime || '',
          rawData: row
        }))
        
        // 尝试从本地存储获取额外信息（如商品名称、数量）
        const localOrders = this.loadLocalTransferOrders()
        
        // 合并明道云数据和本地数据
        const enrichedOrders = transferOrders.map(cloudOrder => {
          const localOrder = localOrders.find(local => local.transferNumber === cloudOrder.transferNumber)
          return {
            ...cloudOrder,
            productName: localOrder?.productName || '未知商品',
            quantity: cloudOrder.quantity || localOrder?.quantity || 0, // ✅ 优先使用明道云的数量数据
            typeName: cloudOrder.transferType // 已经是中文名称
          }
        })
        
        // 按创建时间倒序排列（最新的在前）
        enrichedOrders.sort((a, b) => new Date(b.createTime) - new Date(a.createTime))
        
        console.log(`获取到 ${enrichedOrders.length} 个移库单`)
        return enrichedOrders
      }
      
      // 如果明道云数据获取失败，回退到本地存储
      console.warn('⚠️ 明道云数据获取失败，使用本地存储数据')
      const localOrders = this.loadLocalTransferOrders()
      return localOrders.sort((a, b) => new Date(b.createTime) - new Date(a.createTime))
      
    } catch (error) {
      console.error('获取移库单列表失败:', error)
      // 回退到本地存储
      const localOrders = this.loadLocalTransferOrders()
      return localOrders.sort((a, b) => new Date(b.createTime) - new Date(a.createTime))
    }
  }

  /**
   * 加载本地存储的移库单数据
   * @returns {Array} 移库单列表
   */
  loadLocalTransferOrders() {
    try {
      const stored = localStorage.getItem('transferOrders')
      return stored ? JSON.parse(stored) : []
    } catch (error) {
      console.error('加载本地移库单数据失败:', error)
      return []
    }
  }

  /**
   * 保存移库单到本地存储
   * @param {Object} transferOrder - 移库单数据
   */
  saveTransferOrderToLocal(transferOrder) {
    try {
      const existingOrders = this.loadLocalTransferOrders()
      existingOrders.push(transferOrder)
      localStorage.setItem('transferOrders', JSON.stringify(existingOrders))
      console.log('移库单已保存到本地存储:', transferOrder.transferNumber)
    } catch (error) {
      console.error('保存移库单到本地存储失败:', error)
    }
  }

  /**
   * 清理本地存储的移库单数据（测试用）
   */
  clearLocalTransferOrders() {
    try {
      localStorage.removeItem('transferOrders')
      console.log('本地移库单数据已清理')
    } catch (error) {
      console.error('清理本地移库单数据失败:', error)
    }
  }

  /**
   * 测试移库单工作表连接和字段结构
   * @returns {Promise<Object>} 测试结果
   */
  async testTransferWorksheetConnection() {
    try {
      console.log('🔍 测试移库单工作表连接...')
      console.log('📋 使用的配置信息:')
      console.log(`  移库单工作表ID: ${this.WORKSHEET_IDS.TRANSFER_ORDERS}`)
      console.log(`  移库类型字段ID: ${this.FIELD_IDS.TRANSFER_TYPE}`)
      console.log(`  移库单号字段ID: ${this.FIELD_IDS.TRANSFER_NUMBER}`)
      console.log(`  移库状态字段ID: ${this.FIELD_IDS.TRANSFER_STATUS}`)
      
      // 获取移库单工作表的前几条记录
      console.log('📤 发送API请求...')
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.TRANSFER_ORDERS,
        pageSize: 3
      })
      
      console.log('📥 收到API响应:')
      console.log('  响应存在:', !!response)
      console.log('  响应类型:', typeof response)
      console.log('  完整响应:', response)
      
      if (response) {
        console.log('  data字段存在:', 'data' in response)
        console.log('  data类型:', typeof response.data)
        console.log('  data长度:', response.data?.length)
      }
      
      console.log('📊 移库单工作表连接测试结果:', {
        成功: !!response,
        有数据: !!(response && response.data),
        记录数: response?.data?.length || 0,
        工作表ID: this.WORKSHEET_IDS.TRANSFER_ORDERS
      })
      
      if (response && response.data && response.data.length > 0) {
        console.log('📋 移库单工作表示例数据:')
        response.data.forEach((record, index) => {
          console.log(`  记录 ${index + 1}:`)
          console.log(`    rowid: ${record.rowid}`)
          console.log(`    创建时间: ${record.ctime}`)
          console.log(`    所有字段键:`, Object.keys(record))
          console.log(`    原始记录:`, record)
          
          // 检查已知字段
          console.log(`    移库类型字段值: ${record[this.FIELD_IDS.TRANSFER_TYPE]}`)
          console.log(`    移库单号字段值: ${record[this.FIELD_IDS.TRANSFER_NUMBER]}`)
          console.log(`    移库状态字段值: ${record[this.FIELD_IDS.TRANSFER_STATUS]}`)
          
          // 寻找可能的其他字段
          const possibleFields = Object.keys(record).filter(key => 
            !['rowid', 'ctime', 'utime', 'caid', 'uaid'].includes(key) &&
            ![this.FIELD_IDS.TRANSFER_TYPE, this.FIELD_IDS.TRANSFER_NUMBER, this.FIELD_IDS.TRANSFER_STATUS].includes(key)
          )
          console.log(`    其他可能字段:`, possibleFields)
          
          possibleFields.forEach(fieldId => {
            console.log(`      ${fieldId}: ${record[fieldId]}`)
          })
        })
      } else {
        console.warn('⚠️ 没有获取到任何数据，可能的原因:')
        console.warn('  1. 工作表ID不正确')
        console.warn('  2. 工作表为空')
        console.warn('  3. 权限不足')
        console.warn('  4. 网络问题')
      }
      
      return {
        success: !!response,
        recordCount: response?.data?.length || 0,
        hasData: !!(response && response.data && response.data.length > 0),
        rawResponse: response
      }
      
    } catch (error) {
      console.error('❌ 移库单工作表连接测试失败:', error)
      console.error('错误详情:', {
        message: error.message,
        stack: error.stack,
        name: error.name
      })
      return {
        success: false,
        error: error.message,
        errorDetails: error
      }
    }
  }

  /**
   * 验证移库单字段映射（用于调试）
   * @returns {Promise<Object>} 验证结果
   */
  async validateTransferFieldMapping() {
    try {
      console.log('🔍 开始验证移库单字段映射...')
      
      // 获取移库单工作表的一条记录来验证字段
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.TRANSFER_ORDERS,
        pageSize: 1
      })
      
      if (response && response.data && response.data.length > 0) {
        const record = response.data[0]
        console.log('📋 移库单工作表记录示例:', record)
        
        const fieldValidation = {
          移库类型: {
            字段ID: this.FIELD_IDS.TRANSFER_TYPE,
            当前值: record[this.FIELD_IDS.TRANSFER_TYPE],
            字段存在: this.FIELD_IDS.TRANSFER_TYPE in record
          },
          移库单号: {
            字段ID: this.FIELD_IDS.TRANSFER_NUMBER,
            当前值: record[this.FIELD_IDS.TRANSFER_NUMBER],
            字段存在: this.FIELD_IDS.TRANSFER_NUMBER in record
          },
          移库状态: {
            字段ID: this.FIELD_IDS.TRANSFER_STATUS,
            当前值: record[this.FIELD_IDS.TRANSFER_STATUS],
            字段存在: this.FIELD_IDS.TRANSFER_STATUS in record
          },
          移出库位: {
            字段ID: this.FIELD_IDS.TRANSFER_FROM_LOCATION,
            当前值: record[this.FIELD_IDS.TRANSFER_FROM_LOCATION],
            字段存在: this.FIELD_IDS.TRANSFER_FROM_LOCATION in record
          },
          移入库位: {
            字段ID: this.FIELD_IDS.TRANSFER_TO_LOCATION,
            当前值: record[this.FIELD_IDS.TRANSFER_TO_LOCATION],
            字段存在: this.FIELD_IDS.TRANSFER_TO_LOCATION in record
          }
        }
        
        console.log('🎯 字段映射验证结果:', fieldValidation)
        
        const allFieldsExist = Object.values(fieldValidation).every(field => field.字段存在)
        const hasData = Object.values(fieldValidation).some(field => field.当前值)
        
        return {
          success: true,
          allFieldsExist,
          hasData,
          fieldValidation,
          message: allFieldsExist ? '所有字段ID正确' : '部分字段ID不存在'
        }
      } else {
        return {
          success: false,
          message: '工作表中没有数据，无法验证字段映射'
        }
      }
      
    } catch (error) {
      console.error('❌ 字段映射验证失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 构建额外的移库单字段（已弃用，现在直接使用准确的字段ID）
   * @param {Object} data - 移库单数据
   * @returns {Promise<Array>} 额外字段控件数组
   */
  async buildAdditionalTransferFields(data) {
    console.log('⚠️ buildAdditionalTransferFields 方法已弃用，现在直接使用准确的字段ID')
    return [] // 不再需要智能检测，直接返回空数组
  }

  // 映射判断方法已移除，现在直接使用准确的字段ID

  /**
   * 更新移库单状态
   * @param {string} transferId - 移库单ID
   * @param {string} status - 新状态
   * @returns {Promise<Object>} 更新结果
   */
  async updateTransferStatus(transferId, status) {
    try {
      console.log(`更新移库单状态: ${transferId} -> ${status}`)
      
      const result = await this.callApi('updateWorksheetRow', {
        worksheetId: this.WORKSHEET_IDS.TRANSFER_ORDERS,
        rowId: transferId,
        controls: [
          {
            controlId: this.FIELD_IDS.TRANSFER_STATUS,
            value: status
          }
        ]
      })
      
      console.log('移库单状态更新成功:', result)
      return {
        success: true,
        data: result
      }
      
    } catch (error) {
      console.error('更新移库单状态失败:', error)
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 执行移库操作
   * @param {Object} transferData - 移库执行数据
   * @returns {Promise<Object>} 执行结果
   */
  async executeTransfer(transferData) {
    try {
      console.log('执行移库操作:', transferData)
      
      const {
        transferId,
        fromLocationId,
        toLocationCode,
        quantity,
        productName,
        transferType
      } = transferData

      // 1. 更新移库单状态为执行中
      await this.updateTransferStatus(transferId, 'executing')
      
      // 2. 减少源库位库存
      if (fromLocationId) {
        await this.updateLocationStock(fromLocationId, -quantity)
      }
      
      // 3. 增加目标库位库存（这里简化处理，实际可能需要创建新记录或更新现有记录）
      // 注意：实际业务中可能需要更复杂的库存管理逻辑
      
      // 4. 更新移库单状态为已完成
      await this.updateTransferStatus(transferId, 'completed')
      
      console.log('移库操作执行成功')
      return {
        success: true,
        message: '移库执行成功'
      }
      
    } catch (error) {
      console.error('执行移库操作失败:', error)
      
      // 如果执行失败，尝试回滚状态
      if (transferData.transferId) {
        try {
          await this.updateTransferStatus(transferData.transferId, 'failed')
        } catch (rollbackError) {
          console.error('状态回滚失败:', rollbackError)
        }
      }
      
      return {
        success: false,
        error: error.message
      }
    }
  }

  /**
   * 更新库位库存
   * @param {string} locationId - 库位记录ID
   * @param {number} quantityChange - 库存变化量（正数增加，负数减少）
   * @returns {Promise<Object>} 更新结果
   */
  async updateLocationStock(locationId, quantityChange) {
    this.ensureInitialized()
    try {
      console.log(`更新库位库存: ${locationId}, 变化量: ${quantityChange}`)
      
      // 首先获取当前库存 - 使用rowId过滤
      const currentData = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_STOCK,
        filters: [{
          filterId: 'rowid',
          values: [locationId],
          dataType: 2,
          spliceType: 1
        }]
      })
      
      if (!currentData || !currentData.data || currentData.data.length === 0) {
        throw new Error('无法获取当前库位库存数据')
      }
      
      const currentRow = currentData.data[0]  // 获取第一条记录
      
      const currentStock = parseInt(currentRow[this.FIELD_IDS.LOCKED_STOCK] || '0')
      const newStock = Math.max(0, currentStock + quantityChange)
      
      console.log(`库存更新: ${currentStock} -> ${newStock}`)
      
      const result = await this.callApi('updateWorksheetRow', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_STOCK,
        rowId: locationId,
        controls: [
          {
            controlId: this.FIELD_IDS.LOCKED_STOCK,
            value: newStock
          }
        ]
      })
      
      return {
        success: true,
        data: result,
        oldStock: currentStock,
        newStock: newStock
      }
      
    } catch (error) {
      console.error('更新库位库存失败:', error)
      throw error
    }
  }

  /**
   * 验证移库数据
   * @param {Object} transferData - 移库数据
   * @returns {Object} 验证结果
   */
  validateTransferData(transferData) {
    const errors = []
    
    const { transferType, productName, quantity, fromLocation, toLocationCode } = transferData
    
    if (!transferType) {
      errors.push('移库类型不能为空')
    }
    
    if (!productName || !productName.trim()) {
      errors.push('商品名称不能为空')
    }
    
    if (!quantity || quantity <= 0) {
      errors.push('移库数量必须大于0')
    }
    
    // 根据移库类型验证库位
    if (transferType === 'normal') {
      if (!fromLocation || !fromLocation.locationCode) {
        errors.push('普通移库必须选择移出库位')
      }
      if (!toLocationCode || !toLocationCode.trim()) {
        errors.push('普通移库必须指定移入库位')
      }
      
      // ✅ 新增：验证移出库位和移入库位不能相同
      if (fromLocation && fromLocation.locationCode && toLocationCode && 
          fromLocation.locationCode.trim() === toLocationCode.trim()) {
        errors.push('移出库位和移入库位不能相同')
      }
    } else if (transferType === 'good-to-bad') {
      if (!fromLocation || !fromLocation.locationCode) {
        errors.push('良品转残必须选择移出库位')
      }
      
      // ✅ 新增：验证移出库位不能是残品库位
      if (fromLocation && fromLocation.locationCode && 
          fromLocation.locationCode.trim() === this.DEFECTIVE_LOCATION) {
        errors.push('良品转残的移出库位不能是残品库位')
      }
    } else if (transferType === 'bad-to-good') {
      if (!toLocationCode || !toLocationCode.trim()) {
        errors.push('残品转良必须指定移入库位')
      }
      
      // ✅ 新增：验证移入库位不能是残品库位
      if (toLocationCode && toLocationCode.trim() === this.DEFECTIVE_LOCATION) {
        errors.push('残品转良的移入库位不能是残品库位')
      }
    }
    
    // 验证数量不超过可用库存
    if (fromLocation) {
      // 优先使用 availableStock，然后是 stockQuantity，最后是 lockedStock
      const maxStock = fromLocation.availableStock || 
                      fromLocation.stockQuantity || 
                      fromLocation.lockedStock || 0;
      
      console.log(`🔍 服务端库存验证:`, {
        商品: productName,
        移库数量: quantity,
        availableStock: fromLocation.availableStock,
        stockQuantity: fromLocation.stockQuantity,
        lockedStock: fromLocation.lockedStock,
        计算的最大库存: maxStock
      });
      
      if (quantity > maxStock) {
        errors.push(`移库数量不能超过可用库存 ${maxStock} 件`)
      }
    }
    
    return {
      isValid: errors.length === 0,
      errors: errors
    }
  }

  /**
   * 异步验证移库数据（包含库位存在性验证）
   * @param {Object} transferData - 移库数据
   * @returns {Promise<Object>} 验证结果
   */
  async validateTransferDataAsync(transferData) {
    console.log('🔒 开始异步验证移库数据:', transferData)
    
    // 只进行基本验证，库位验证已在提交前单独处理
    const basicValidation = this.validateTransferData(transferData)
    
    console.log('🔒 异步验证结果:', basicValidation)
    return basicValidation
  }

  /**
   * 生成移库单号
   * @returns {string} 移库单号
   */
  generateTransferNumber() {
    const now = new Date()
    const dateStr = now.getFullYear() + 
      String(now.getMonth() + 1).padStart(2, '0') + 
      String(now.getDate()).padStart(2, '0')
    const timeStr = String(now.getHours()).padStart(2, '0') + 
      String(now.getMinutes()).padStart(2, '0') + 
      String(now.getSeconds()).padStart(2, '0')
    return `YK${dateStr}${timeStr}`
  }

  /**
   * 暴露给外部调试使用的配置获取方法
   * @param {string} key - 配置键名
   * @returns {string} 配置值
   */
  getEnvValue(key) {
    return getEnvValue(key);
  }

  /**
   * 获取移库类型显示名称
   * @param {string} type - 移库类型代码
   * @returns {string} 显示名称
   */
  getTransferTypeName(type) {
    const typeMap = {
      'normal': '普通移库',      // 第一种拣货方式：普通移库
      'good-to-bad': '良品转残',  // 第二种拣货方式：良品转残
      'bad-to-good': '残品转良'   // 第三种拣货方式：残品转良
    }
    return typeMap[type] || '未知类型'
  }

  /**
   * 获取状态显示名称
   * @param {string} status - 状态代码
   * @returns {string} 显示名称
   */
  getStatusName(status) {
    const statusMap = {
      'pending': '待执行',
      'executing': '执行中', 
      'completed': '已完成',  // ✅ 默认状态，表示移库已完成
      'cancelled': '已取消',
      'failed': '执行失败'
    }
    return statusMap[status] || status
  }

  /**
   * 按商品条码搜索库存信息
   * @param {string} barcode - 商品条码
   * @param {string} transferType - 移库类型
   * @returns {Promise<Array>} 搜索结果
   */
  async searchByBarcode(barcode, transferType) {
    try {
      console.log(`按条码搜索: ${barcode}, 移库类型: ${transferType}`)
      
      if (!barcode || !barcode.trim()) {
        return []
      }

      const searchTerm = barcode.trim()
      console.log(`开始搜索条码: "${searchTerm}"`)

      // 获取所有库位库存数据，不使用任何预过滤
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_STOCK,
        pageSize: 500 // 大幅增加页面大小以确保获取所有数据
      })
      
      console.log(`API返回数据总数: ${response?.data?.length || 0}`)
      
      if (response && response.data) {
        console.log('开始过滤数据...')
        
        let allResults = response.data.map((row, index) => {
          const productName = row[this.FIELD_IDS.PRODUCT_NAME] || ''
          const productBarcode = row[this.FIELD_IDS.PRODUCT_BARCODE] || ''
          const supplierName = row[this.FIELD_IDS.SUPPLIER_NAME] || ''
          const locationCode = row[this.FIELD_IDS.LOCATION_CODE] || ''
          const availableStock = parseInt(row[this.FIELD_IDS.AVAILABLE_STOCK] || '0') // ✅ 新增可用库存字段
          const lockedStock = parseInt(row[this.FIELD_IDS.LOCKED_STOCK] || '0')
          const stockQuantity = parseInt(row[this.FIELD_IDS.STOCK_QUANTITY] || '0')
          
          // 输出前几条数据用于调试
          if (index < 3) {
            console.log(`📦 数据示例 ${index + 1}:`, {
              productName,
              productBarcode,
              locationCode,
              availableStock, // ✅ 显示可用库存
              lockedStock,
              stockQuantity,
              supplierName
            })
          }
          
          return {
            id: row.rowid,
            productName,
            productBarcode,
            supplierName,
            locationCode,
            availableStock, // ✅ 新增可用库存字段
            lockedStock,
            stockQuantity,
            rawData: row
          }
        })
        
        console.log(`映射后数据总数: ${allResults.length}`)

        // 第一步：过滤有库存的数据（使用可用库存优先）
        let stockFiltered = allResults.filter((item, index) => {
          const hasStock = item.availableStock > 0 || item.lockedStock > 0 || item.stockQuantity > 0 // ✅ 优先检查可用库存
          const hasBasicInfo = item.productName && item.locationCode
          
          // 调试每个项目的库存状态
          if (index < 10 || hasStock) {
            console.log(`📊 初步库存过滤 #${index}: ${item.productName}`, {
              库位: item.locationCode,
              可用库存: item.availableStock, // ✅ 显示可用库存
              锁定库存: item.lockedStock,
              总库存: item.stockQuantity,
              有库存: hasStock,
              有基本信息: hasBasicInfo,
              通过: hasStock && hasBasicInfo
            })
          }
          
          return hasStock && hasBasicInfo
        })
        
        console.log(`有库存的数据: ${stockFiltered.length} 条`)

        // 第二步：条码匹配（使用更宽松的匹配策略）
        let matched = stockFiltered.filter((item, index) => {
          const searchLower = searchTerm.toLowerCase()
          const productNameLower = item.productName.toLowerCase()
          const supplierNameLower = item.supplierName.toLowerCase()
          
          // 宽松匹配策略
          const matches = [
            // 1. 直接包含匹配
            {
              result: productNameLower.includes(searchLower),
              type: '商品名称包含'
            },
            {
              result: supplierNameLower.includes(searchLower),
              type: '供应商名称包含'
            },
            
            // 2. 商品条码字段直接匹配 ✅ 修复核心逻辑
            (() => {
              const barcode = item.productBarcode || ''
              const result = barcode && (
                barcode.toLowerCase() === searchLower ||
                barcode.toLowerCase().includes(searchLower) ||
                searchLower.includes(barcode.toLowerCase()) ||
                barcode === searchTerm // 精确匹配
              )
              return {
                result: result,
                type: `商品条码字段匹配(${barcode})`,
                barcode
              }
            })(),
            
            // 2.5. 备用：从商品名称提取条码匹配
            (() => {
              const extracted = this.extractBarcode(item.productName)
              const result = extracted && (
                extracted.toLowerCase() === searchLower ||
                extracted.toLowerCase().includes(searchLower) ||
                searchLower.includes(extracted.toLowerCase())
              )
              return {
                result: result,
                type: `商品名称提取条码匹配(${extracted})`,
                extracted
              }
            })(),
            
            // 2.5. 直接在商品名称中搜索条码（当无法提取条码时的备选方案）
            {
              result: item.productName.includes(searchTerm),
              type: '商品名称直接包含搜索词'
            },
            
            // 3. 数字匹配（如果搜索词是纯数字）
            {
              result: /^\d+$/.test(searchTerm) && (
                productNameLower.includes(searchTerm) ||
                item.productName.includes(searchTerm)
              ),
              type: '数字匹配'
            },
            
            // 4. 忽略特殊字符的匹配
            {
              result: productNameLower.replace(/[-_\s]/g, '').includes(searchLower.replace(/[-_\s]/g, '')),
              type: '忽略特殊字符匹配'
            },
            
            // 5. 移除库位编码匹配，避免条码搜索时误匹配库位
            
            // 6. 模糊匹配（容错处理）
            {
              result: this.fuzzyMatch(searchTerm, item.productName, 0.7),
              type: '模糊匹配'
            }
          ]
          
          const matchedStrategies = matches.filter(m => m.result)
          const isMatch = matchedStrategies.length > 0
          
          // 输出匹配调试信息（限制输出数量）
          if (index < 10 || isMatch) {
            console.log(`${isMatch ? '✓' : '✗'} 匹配检查 - ${item.productName}:`, {
              searchTerm,
              库位: item.locationCode,
              库存: item.lockedStock,
              匹配策略: matchedStrategies.map(m => m.type),
              isMatch
            })
          }
          
          return isMatch
        })
        
        console.log(`条码匹配结果: ${matched.length} 条`)

        // 第三步：转换为标准格式
        let results = matched.map(item => {
          return {
            id: item.id,
            productName: item.productName,
            barcode: item.productBarcode || this.extractBarcode(item.productName) || '',
            locationCode: item.locationCode,
            supplierName: item.supplierName,
            productionDate: item.rawData[this.FIELD_IDS.PRODUCTION_DATE] || '',
            availableStock: item.availableStock, // ✅ 使用真实的可用库存字段
            lockedStock: item.lockedStock,
            stockQuantity: item.stockQuantity,
            rawData: item.rawData
          }
        })

        console.log(`格式化后结果: ${results.length} 条`)

        // 第四步：根据移库类型过滤结果
        const beforeTypeFilter = results.length
        console.log(`⚠️ [条码搜索] 准备进行移库类型过滤，当前结果数: ${beforeTypeFilter}`)
        
        // 显示过滤前的数据详情
        results.forEach((item, index) => {
          console.log(`📦 [条码搜索] 过滤前数据 #${index}:`, {
            商品: item.productName,
            库位: item.locationCode,
            锁定库存: item.lockedStock,
            总库存: item.stockQuantity,
            可用库存: item.availableStock
          })
        })
        
        results = this.filterByTransferType(results, transferType)
        console.log(`🎯 [条码搜索] 移库类型过滤完成: ${beforeTypeFilter} -> ${results.length} 条`)
        
        // 第五步：按库存数量排序（可用库存多的在前）
        results.sort((a, b) => b.availableStock - a.availableStock)
        
        console.log(`最终条码搜索结果: ${results.length} 条`)
        
        // 输出前几个结果用于调试
        results.slice(0, 3).forEach((result, index) => {
          console.log(`结果 ${index + 1}:`, {
            productName: result.productName,
            barcode: result.barcode,
            locationCode: result.locationCode,
            availableStock: result.availableStock
          })
        })
        
        return results
      }
      
      console.log('API未返回数据')
      return []
      
    } catch (error) {
      console.error('按条码搜索失败:', error)
      throw error
    }
  }

  /**
   * 按库位编码搜索库存信息
   * @param {string} locationCode - 库位编码
   * @param {string} transferType - 移库类型
   * @returns {Promise<Array>} 搜索结果
   */
  async searchByLocationCode(locationCode, transferType) {
    try {
      console.log(`按库位搜索: ${locationCode}, 移库类型: ${transferType}`)
      
      if (!locationCode || !locationCode.trim()) {
        return []
      }

      const searchTerm = locationCode.trim()
      console.log(`开始搜索库位: "${searchTerm}"`)

      // 获取所有库位库存数据，不使用任何预过滤
      const response = await this.callApi('getFilterRows', {
        worksheetId: this.WORKSHEET_IDS.LOCATION_STOCK,
        pageSize: 500 // 大幅增加页面大小以确保获取所有数据
      })
      
      console.log(`API返回数据总数: ${response?.data?.length || 0}`)
      
      if (response && response.data) {
        console.log('开始过滤库位数据...')
        
        let allResults = response.data.map((row, index) => {
          const productName = row[this.FIELD_IDS.PRODUCT_NAME] || ''
          const productBarcode = row[this.FIELD_IDS.PRODUCT_BARCODE] || ''
          const supplierName = row[this.FIELD_IDS.SUPPLIER_NAME] || ''
          const currentLocationCode = row[this.FIELD_IDS.LOCATION_CODE] || ''
          const availableStock = parseInt(row[this.FIELD_IDS.AVAILABLE_STOCK] || '0') // ✅ 新增可用库存字段
          const lockedStock = parseInt(row[this.FIELD_IDS.LOCKED_STOCK] || '0')
          const stockQuantity = parseInt(row[this.FIELD_IDS.STOCK_QUANTITY] || '0')
          
          // 输出前几条数据用于调试
          if (index < 3) {
            console.log(`📦 库位数据示例 ${index + 1}:`, {
              productName,
              productBarcode,
              currentLocationCode,
              availableStock, // ✅ 显示可用库存
              lockedStock,
              stockQuantity,
              supplierName
            })
          }
          
          return {
            id: row.rowid,
            productName,
            productBarcode,
            supplierName,
            locationCode: currentLocationCode,
            availableStock, // ✅ 新增可用库存字段
            lockedStock,
            stockQuantity,
            rawData: row
          }
        })
        
        console.log(`映射后数据总数: ${allResults.length}`)

        // 第一步：过滤有库存的数据（使用可用库存优先）
        let stockFiltered = allResults.filter((item, index) => {
          const hasStock = item.availableStock > 0 || item.lockedStock > 0 || item.stockQuantity > 0 // ✅ 优先检查可用库存
          const hasBasicInfo = item.productName && item.locationCode
          
          // 调试每个项目的库存状态
          if (index < 10 || hasStock) {
            console.log(`📊 库位搜索-初步库存过滤 #${index}: ${item.productName}`, {
              库位: item.locationCode,
              可用库存: item.availableStock, // ✅ 显示可用库存
              锁定库存: item.lockedStock,
              总库存: item.stockQuantity,
              有库存: hasStock,
              有基本信息: hasBasicInfo,
              通过: hasStock && hasBasicInfo
            })
          }
          
          return hasStock && hasBasicInfo
        })
        
        console.log(`有库存的库位数据: ${stockFiltered.length} 条`)

        // 第二步：库位编码精确匹配（修复误匹配问题）
        let matched = stockFiltered.filter((item, index) => {
          const searchTrimmed = searchTerm.trim()
          const currentLocationTrimmed = item.locationCode.trim()
          
          // 🎯 使用精确匹配策略，避免误匹配
          const matches = [
            // 1. 完全精确匹配（大小写不敏感）
            {
              result: currentLocationTrimmed.toLowerCase() === searchTrimmed.toLowerCase(),
              type: '精确匹配',
              priority: 1
            },
            
            // 2. 去除连字符后的精确匹配
            (() => {
              const normalizedCurrent = currentLocationTrimmed.replace(/[-_\s]/g, '').toLowerCase()
              const normalizedSearch = searchTrimmed.replace(/[-_\s]/g, '').toLowerCase()
              const result = normalizedCurrent === normalizedSearch
              return {
                result,
                type: `去连字符精确匹配(${normalizedCurrent})`,
                priority: 2
              }
            })(),
            
            // 3. 标准化格式后的精确匹配
            (() => {
              const normalizedCurrent = this.normalizeLocationCode(item.locationCode)
              const normalizedSearch = this.normalizeLocationCode(searchTerm)
              const result = normalizedCurrent.toLowerCase() === normalizedSearch.toLowerCase()
              return {
                result,
                type: `标准化精确匹配(${normalizedCurrent})`,
                priority: 3
              }
            })()
          ]
          
          // 只使用匹配成功的策略中优先级最高的
          const successfulMatches = matches.filter(m => m.result)
          const isMatch = successfulMatches.length > 0
          
          // 输出匹配调试信息（限制输出数量）
          if (index < 10 || isMatch) {
            console.log(`${isMatch ? '✓' : '✗'} 库位精确匹配检查 - ${item.locationCode}:`, {
              searchTerm: searchTrimmed,
              商品: item.productName,
              库存: item.lockedStock,
              匹配策略: successfulMatches.map(m => `${m.type}(优先级${m.priority})`),
              isMatch
            })
          }
          
          return isMatch
        })
        
        console.log(`库位匹配结果: ${matched.length} 条`)

        // 第三步：转换为标准格式
        let results = matched.map(item => {
          return {
            id: item.id,
            productName: item.productName,
            barcode: item.productBarcode || this.extractBarcode(item.productName) || '',
            locationCode: item.locationCode,
            supplierName: item.supplierName,
            productionDate: item.rawData[this.FIELD_IDS.PRODUCTION_DATE] || '',
            availableStock: item.availableStock, // ✅ 使用真实的可用库存字段
            lockedStock: item.lockedStock,
            stockQuantity: item.stockQuantity,
            rawData: item.rawData
          }
        })

        console.log(`格式化后结果: ${results.length} 条`)

        // 第四步：根据移库类型过滤结果
        const beforeTypeFilter = results.length
        console.log(`⚠️ [库位搜索] 准备进行移库类型过滤，当前结果数: ${beforeTypeFilter}`)
        
        // 显示过滤前的数据详情
        results.forEach((item, index) => {
          console.log(`📦 [库位搜索] 过滤前数据 #${index}:`, {
            商品: item.productName,
            库位: item.locationCode,
            锁定库存: item.lockedStock,
            总库存: item.stockQuantity,
            可用库存: item.availableStock
          })
        })
        
        results = this.filterByTransferType(results, transferType)
        console.log(`🎯 [库位搜索] 移库类型过滤完成: ${beforeTypeFilter} -> ${results.length} 条`)
        
        // 第五步：按库位编码和库存数量排序
        results.sort((a, b) => {
          // 首先按库位编码排序（精确匹配的在前）
          const aExact = a.locationCode.toLowerCase() === searchTerm.toLowerCase()
          const bExact = b.locationCode.toLowerCase() === searchTerm.toLowerCase()
          
          if (aExact && !bExact) return -1
          if (!aExact && bExact) return 1
          
          // 然后按库位编码字典序排序
          const locationCompare = a.locationCode.localeCompare(b.locationCode)
          if (locationCompare !== 0) return locationCompare
          
          // 最后按可用库存排序（库存多的在前）
          return b.availableStock - a.availableStock
        })
        
        console.log(`最终库位搜索结果: ${results.length} 条`)
        
        // 输出前几个结果用于调试
        results.slice(0, 3).forEach((result, index) => {
          console.log(`库位结果 ${index + 1}:`, {
            productName: result.productName,
            locationCode: result.locationCode,
            availableStock: result.availableStock
          })
        })
        
        return results
      }
      
      console.log('API未返回库位数据')
      return []
      
    } catch (error) {
      console.error('按库位搜索失败:', error)
      throw error
    }
  }

  /**
   * 根据移库类型过滤结果
   * @param {Array} results - 搜索结果
   * @param {string} transferType - 移库类型
   * @returns {Array} 过滤后的结果
   */
  filterByTransferType(results, transferType) {
    console.log(`🎯 开始移库类型过滤: ${transferType}, 原始结果: ${results.length} 条`)
    
    const filtered = results.filter((item, index) => {
      // 基础验证：必须有完整的商品信息
      if (!item.productName || !item.locationCode) {
        console.warn(`⚠️ 商品信息不完整，跳过 #${index}:`, item)
        return false
      }
      
      // 放宽库存检查条件 - 优先使用可用库存
      const availableStock = parseInt(item.availableStock || 0) // ✅ 新增可用库存
      const lockedStock = parseInt(item.lockedStock || 0)
      const stockQuantity = parseInt(item.stockQuantity || 0)
      const hasAnyStock = availableStock > 0 || lockedStock > 0 || stockQuantity > 0 // ✅ 优先检查可用库存
      
      console.log(`📊 库存检查 #${index} - ${item.productName}:`, {
        库位: item.locationCode,
        可用库存: `${item.availableStock} -> ${availableStock}`, // ✅ 显示可用库存
        锁定库存: `${item.lockedStock} -> ${lockedStock}`,
        总库存: `${item.stockQuantity} -> ${stockQuantity}`,
        有库存: hasAnyStock
      })
      
      if (!hasAnyStock) {
        console.warn(`⚠️ 无任何库存，跳过 #${index}:`, {
          商品: item.productName,
          库位: item.locationCode,
          可用库存: `${item.availableStock} -> ${availableStock}`, // ✅ 显示可用库存
          锁定库存: `${item.lockedStock} -> ${lockedStock}`,
          总库存: `${item.stockQuantity} -> ${stockQuantity}`
        })
        return false
      }
      
      let shouldInclude = false
      let reason = ''
      
      // 根据移库类型进行过滤
      if (transferType === 'bad-to-good') {
        // 残品转良：只显示CP-01-01-01-01库位的商品，且必须有库存
        shouldInclude = item.locationCode === this.DEFECTIVE_LOCATION
        reason = shouldInclude ? '残品库位匹配' : `非残品库位(${item.locationCode})`
        
      } else if (transferType === 'good-to-bad') {
        // 良品转残：排除特殊库位，必须是正常库位的良品
        shouldInclude = !this.EXCLUDED_LOCATIONS.includes(item.locationCode)
        reason = shouldInclude ? '正常库位' : `特殊库位(${item.locationCode})`
        
      } else if (transferType === 'normal') {
        // 普通移库：排除特殊库位
        shouldInclude = !this.EXCLUDED_LOCATIONS.includes(item.locationCode)
        reason = shouldInclude ? '正常库位' : `特殊库位(${item.locationCode})`
        
      } else {
        // 未知移库类型，保守处理，但不过于严格
        shouldInclude = !this.EXCLUDED_LOCATIONS.includes(item.locationCode)
        reason = shouldInclude ? `未知类型-允许(${item.locationCode})` : `未知类型-特殊库位(${item.locationCode})`
        console.warn(`⚠️ 未知移库类型: ${transferType}`)
      }
      
      // 记录过滤决策（显示所有决策过程）
      console.log(`${shouldInclude ? '✅' : '❌'} 移库类型过滤 #${index} - ${item.productName}:`, {
        库位: item.locationCode,
        移库类型: transferType,
        排除库位列表: this.EXCLUDED_LOCATIONS,
        残品库位: this.DEFECTIVE_LOCATION,
        是否在排除列表: this.EXCLUDED_LOCATIONS.includes(item.locationCode),
        决策: reason,
        通过: shouldInclude
      })
      
      return shouldInclude
    })
    
    console.log(`🎯 移库类型过滤完成: ${results.length} -> ${filtered.length} 条`)
    
    // 如果过滤后结果为空，提供详细的分析
    if (filtered.length === 0 && results.length > 0) {
      console.warn('⚠️ 移库类型过滤后无结果，原因分析:')
      
      const locationAnalysis = {}
      results.forEach(item => {
        const loc = item.locationCode
        if (!locationAnalysis[loc]) {
          locationAnalysis[loc] = 0
        }
        locationAnalysis[loc]++
      })
      
      console.warn('📊 库位分布:', locationAnalysis)
      console.warn('🚫 排除库位:', this.EXCLUDED_LOCATIONS)
      console.warn('🎯 目标库位(残品转良):', this.DEFECTIVE_LOCATION)
    }
    
    return filtered
  }

  /**
   * 验证库存数据完整性
   * @param {Object} item - 库存项目
   * @returns {Object} 验证结果
   */
  validateInventoryItem(item) {
    const errors = []
    const warnings = []
    const debugInfo = []
    
    // 必填字段检查
    if (!item.productName || item.productName.trim() === '') {
      errors.push('商品名称不能为空')
    } else {
      debugInfo.push(`商品名称: "${item.productName}"`)
    }
    
    if (!item.locationCode || item.locationCode.trim() === '') {
      errors.push('库位编码不能为空')
    } else {
      debugInfo.push(`库位编码: "${item.locationCode}"`)
    }
    
    // 库存数量检查
    const lockedStock = parseInt(item.lockedStock || 0)
    const stockQuantity = parseInt(item.stockQuantity || 0)
    
    debugInfo.push(`库存数据: 锁定=${lockedStock}, 总量=${stockQuantity}`)
    
    // 修改库存验证逻辑 - 放宽条件
    if (lockedStock <= 0 && stockQuantity <= 0) {
      warnings.push('无可用库存（锁定库存和总库存均为0）')
    } else if (lockedStock <= 0 && stockQuantity > 0) {
      warnings.push('锁定库存为0但总库存大于0，可能需要检查库存状态')
    }
    
    if (lockedStock > stockQuantity && stockQuantity > 0) {
      warnings.push(`锁定库存(${lockedStock})大于总库存(${stockQuantity})，数据可能有误`)
    }
    
    // 日期检查
    if (item.productionDate && item.productionDate.trim() !== '') {
      try {
        const prodDate = new Date(item.productionDate)
        const now = new Date()
        const diffYears = (now - prodDate) / (1000 * 60 * 60 * 24 * 365)
        if (diffYears > 10) {
          warnings.push('商品生产日期超过10年，请确认数据正确性')
        }
        debugInfo.push(`生产日期: ${item.productionDate}`)
      } catch (e) {
        warnings.push('生产日期格式不正确')
      }
    }
    
    // 供应商信息检查
    if (!item.supplierName || item.supplierName.trim() === '') {
      warnings.push('供应商信息为空')
    } else {
      debugInfo.push(`供应商: "${item.supplierName}"`)
    }
    
    // 计算可用库存（使用更灵活的逻辑）
    const availableStock = Math.max(lockedStock, stockQuantity, 0)
    
    const result = {
      isValid: errors.length === 0, // 只有错误才会导致验证失败
      errors,
      warnings,
      debugInfo,
      item: {
        ...item,
        lockedStock,
        stockQuantity,
        availableStock // 使用计算出的可用库存
      }
    }
    
    // 详细的验证日志
    if (errors.length > 0 || warnings.length > 0) {
      console.log(`📋 库存验证 - ${item.productName || '未知商品'}:`, {
        isValid: result.isValid,
        errors,
        warnings,
        debugInfo,
        availableStock
      })
    }
    
    return result
  }

  /**
   * 从商品名称中提取条码（增强处理）
   * @param {string} productName - 商品名称
   * @returns {string} 提取的条码
   */
  extractBarcode(productName) {
    if (!productName || typeof productName !== 'string') {
      return ''
    }
    
    // 多种条码提取策略，按优先级排序
    const strategies = [
      // 1. 提取8-18位连续数字（最常见的条码格式）
      {
        pattern: /\b\d{8,18}\b/g,
        name: '连续数字条码'
      },
      
      // 2. 提取字母+数字组合的条码
      {
        pattern: /\b[A-Z]{2,4}\d{6,15}\b/gi,
        name: '字母数字条码'
      },
      
      // 3. 提取数字+字母+数字的混合条码
      {
        pattern: /\b\d{2,4}[A-Z]{1,3}\d{6,12}\b/gi,
        name: '混合条码'
      },
      
      // 4. 提取纯数字序列（作为备选）
      {
        pattern: /\d{6,}/g,
        name: '数字序列'
      },
      
      // 5. 提取包含连字符的条码
      {
        pattern: /\b[A-Z0-9]{2,}-[A-Z0-9]{2,}-[A-Z0-9]{2,}\b/gi,
        name: '连字符条码'
      }
    ]
    
    for (const strategy of strategies) {
      const matches = productName.match(strategy.pattern)
      if (matches && matches.length > 0) {
        // 返回最长的匹配结果
        const result = matches.reduce((longest, current) => 
          current.length > longest.length ? current : longest, '')
        
        // 调试输出条码提取结果
        console.log(`条码提取成功 - 策略: ${strategy.name}, 原文: "${productName}", 提取结果: "${result}"`)
        return result
      }
    }
    
    console.log(`条码提取失败 - 商品名称: "${productName}"`)
    return ''
  }

  /**
   * 标准化库位编码格式
   * @param {string} locationCode - 库位编码
   * @returns {string} 标准化的库位编码
   */
  normalizeLocationCode(locationCode) {
    if (!locationCode || typeof locationCode !== 'string') {
      return ''
    }
    
    // 移除空格并转换为大写
    let normalized = locationCode.trim().toUpperCase()
    
    // 标准化连字符格式
    // 例如：A010101 -> A01-01-01, CP01010101 -> CP-01-01-01-01
    if (!/[-]/.test(normalized)) {
      // 如果没有连字符，尝试添加标准格式
      if (normalized.match(/^[A-Z]{1,2}\d{6}$/)) {
        // 单字母+6位数字: A010101 -> A01-01-01
        normalized = normalized.replace(/^([A-Z])(\d{2})(\d{2})(\d{2})$/, '$1$2-$3-$4')
      } else if (normalized.match(/^[A-Z]{2}\d{8}$/)) {
        // 双字母+8位数字: CP01010101 -> CP-01-01-01-01
        normalized = normalized.replace(/^([A-Z]{2})(\d{2})(\d{2})(\d{2})(\d{2})$/, '$1-$2-$3-$4-$5')
      }
    }
    
    return normalized
  }

  /**
   * 模糊匹配算法
   * @param {string} query - 查询字符串
   * @param {string} target - 目标字符串
   * @param {number} threshold - 相似度阈值（0-1）
   * @returns {boolean} 是否匹配
   */
  fuzzyMatch(query, target, threshold = 0.6) {
    if (!query || !target) return false
    
    const queryLower = query.toLowerCase()
    const targetLower = target.toLowerCase()
    
    // 简单的Levenshtein距离算法
    const matrix = []
    for (let i = 0; i <= queryLower.length; i++) {
      matrix[i] = [i]
    }
    for (let j = 0; j <= targetLower.length; j++) {
      matrix[0][j] = j
    }
    
    for (let i = 1; i <= queryLower.length; i++) {
      for (let j = 1; j <= targetLower.length; j++) {
        if (queryLower.charAt(i - 1) === targetLower.charAt(j - 1)) {
          matrix[i][j] = matrix[i - 1][j - 1]
        } else {
          matrix[i][j] = Math.min(
            matrix[i - 1][j - 1] + 1, // 替换
            matrix[i][j - 1] + 1,     // 插入
            matrix[i - 1][j] + 1      // 删除
          )
        }
      }
    }
    
    const distance = matrix[queryLower.length][targetLower.length]
    const maxLength = Math.max(queryLower.length, targetLower.length)
    const similarity = 1 - distance / maxLength
    
    return similarity >= threshold
  }

  /**
   * 智能搜索 - 自动检测输入类型并搜索
   * @param {string} query - 搜索查询
   * @param {string} transferType - 移库类型
   * @returns {Promise<Array>} 搜索结果
   */
  async smartSearch(query, transferType) {
    try {
      console.log(`\n🔍 智能搜索开始: "${query}", 移库类型: ${transferType}`)
      
      if (!query || !query.trim()) {
        return []
      }

      const trimmed = query.trim()
      
      // 自动检测搜索类型
      const isLocationCode = this.isLocationCode(trimmed)
      const isBarcode = this.isBarcode(trimmed)
      
      console.log(`🔍 搜索类型检测: 库位编码=${isLocationCode}, 条码=${isBarcode}`)
      
      let results = []
      
      if (isLocationCode) {
        console.log('📍 执行库位编码搜索')
        results = await this.searchByLocationCode(trimmed, transferType)
      } else if (isBarcode) {
        console.log('🏷️ 执行商品条码搜索')
        results = await this.searchByBarcode(trimmed, transferType)
      } else {
        console.log('🔀 类型不确定，执行混合搜索')
        // 不确定类型时，同时搜索两种类型
        const [barcodeResults, locationResults] = await Promise.all([
          this.searchByBarcode(trimmed, transferType).catch(err => {
            console.warn('❌ 条码搜索失败:', err.message)
            return []
          }),
          this.searchByLocationCode(trimmed, transferType).catch(err => {
            console.warn('❌ 库位搜索失败:', err.message)
            return []
          })
        ])
        
        console.log(`🔀 混合搜索结果: 条码搜索=${barcodeResults.length}条, 库位搜索=${locationResults.length}条`)
        
        // 合并结果并去重
        const combinedResults = [...barcodeResults]
        locationResults.forEach(item => {
          if (!combinedResults.find(existing => existing.id === item.id)) {
            combinedResults.push(item)
          }
        })
        
        results = combinedResults
      }
      
      console.log(`🎯 初步搜索结果: ${results.length} 条`)
      
      // 对搜索结果进行验证和清理
      const validatedResults = []
      for (const item of results) {
        const validation = this.validateInventoryItem(item)
        
        if (validation.isValid) {
          // 记录警告但不阻止显示
          if (validation.warnings.length > 0) {
            console.warn(`⚠️ 商品 ${item.productName} 存在警告:`, validation.warnings)
          }
          validatedResults.push(validation.item)
        } else {
          console.warn(`❌ 商品 ${item.productName} 验证失败:`, validation.errors)
        }
      }
      
      console.log(`\n✅ 智能搜索完成，返回 ${validatedResults.length} 条有效结果`)
      
      // 输出前3个结果用于验证
      validatedResults.slice(0, 3).forEach((result, index) => {
        console.log(`📦 结果 ${index + 1}: ${result.productName} | 库位: ${result.locationCode} | 库存: ${result.availableStock}`)
      })
      
      return validatedResults
      
    } catch (error) {
      console.error('❌ 智能搜索失败:', error)
      throw error
    }
  }

  /**
   * 检测是否为库位编码
   * @param {string} input - 输入字符串
   * @returns {boolean} 是否为库位编码
   */
  isLocationCode(input) {
    if (!input) return false
    
    // 库位编码特征：字母开头 + 数字组合，可能包含连字符
    const locationPatterns = [
      /^[A-Z]{1,2}-?\d{2}-\d{2}-\d{2}(-\d{2})?$/i, // 标准格式如: A01-01-01, CP-01-01-01-01
      /^(JH|CP|SH|CY|A|B|C|D|E|F)-\d{2}-\d{2}-\d{2}(-\d{2})?$/i // 带前缀的格式
    ]
    
    return locationPatterns.some(pattern => pattern.test(input))
  }

  /**
   * 检测是否为商品条码
   * @param {string} input - 输入字符串
   * @returns {boolean} 是否为商品条码
   */
  isBarcode(input) {
    if (!input) return false
    
    // 商品条码特征
    const barcodePatterns = [
      /^\d{8,18}$/, // 纯数字条码，8-18位
      /^[A-Z0-9]{6,20}$/i, // 字母数字混合条码
      /^[A-Z]{2,4}\d{6,15}$/i // 字母前缀 + 数字
    ]
    
    return barcodePatterns.some(pattern => pattern.test(input))
  }
}

// 导出单例实例
const transferApi = new TransferApiService()
export default transferApi